package main

import (
	"fmt"
	"sync"
)

/**
sync.Map
解释：
	一个线程安全集合，内部通过原子访问和锁机制实现结合的线程安全
应用场景：
	1、适合读多写少
	2、在key值已存在的情况下，可以无锁修改其value，比普通map + 锁 性能更好
*/

func main() {
	MapSyncCaseUse()
	MapSyncCount()
}

func MapSyncCaseUse() {
	mp := sync.Map{}
	// 1、Store: 设置键值对
	mp.Store("name", "zhangsan")
	mp.Store("age", 18)
	mp.Store("email", "110900@email.com")

	// 2、Load: 通过key获取value, 如果不存在则返回nil, 存在则返回false
	fmt.Println(mp.Load("name"))  // zhangsan true
	fmt.Println(mp.Load("age"))   // 18 true
	fmt.Println(mp.Load("email")) // 110900@email.com true

	// 3、LoadOrStore: 通过key获取value, 如果不存在则返回设置好的默认值
	fmt.Println(mp.LoadOrStore("hobby", "篮球")) // 篮球 false
	fmt.Println(mp.LoadOrStore("weight", 120)) // 120 false

	// 4、LoadAndDelete: 通过key获取vaue后，删除该key
	fmt.Println(mp.LoadAndDelete("hobby"))  // 篮球 true
	fmt.Println(mp.LoadAndDelete("hobby1")) // <nil> false

	// 5、Range: 遍历
	mp.Range(func(key, value interface{}) bool {
		fmt.Println(key, value)
		/**
		weight 120
		name zhangsan
		age 18
		email 110900@email.com
		*/
		return true
	})
	fmt.Println("mp case use:", mp)
	// 输出 -> mp: {{0 0} {{map[age:0xc000112020 email:0xc000112028 name:0xc000112018 weight:0xc000112040] false}} map[] 0}
}

// 案例: 通过sync.Map实现array元素值的计数
func MapSyncCount() {
	mp := sync.Map{}
	list := []string{"a", "b", "c", "d", "e", "f", "a", "e", "b", "a"}
	for _, value := range list {
		current, ok := mp.Load(value)
		if !ok {
			mp.Store(value, 1)
		} else {
			temp := current.(int) + 1
			mp.Store(value, temp)
		}
	}
	mp.Range(func(key, value interface{}) bool {
		fmt.Printf("key: %s, value: %d\n", key, value)
		return true
	})
}
